#!/usr/bin/env python

"""
LiWE invoke
===========

This is the liwe ``invoke()`` method.

In LiWE *invoke()ing* means load up in memory a single module and executing the desired command (method).

In LiWE you can specify the command to be executed in one of the following ways:

	- By specifying two attributes:

		- module:	the module to be loaded
		- command:	the command to be executed on the specified ``module``

	- By specifying a *simple* dotted notation, this way:

		- command:	the command in the *simple* dotted notation.
				For example: module.command

	- By specifying a *complete* dotted notation, this way:

		- command:	the command in the *complete* dotted notation.
				For example: modname.file.method

If you specify a *simple* dotted notation, the ``modname`` and ``file`` will overlap.

"""

import cgi, sys

def invoke ( h ):
	"""
	
	"""
	fields = cgi.FieldStorage ()
	
	dct = {}
	for f in fields:
		if f in ( "module", "command" ): continue
		dct [ f ] = fields [ f ].value

	command = None
	module  = None
	modbase = None

	try:
		command = fields [ 'command' ].value
		module = fields [ 'module' ].value
	except:
		if command:
			"""
			Se c'e' ``command``, potrebbe essere che stia usando la "dotted notation"
			per invocare il metodo, tipo "modulo.submodulo.metodo", quindi devo provare
			a parsare command.
			"""

			vals = command.split ( "." )

			if len ( vals ) > 1:
				command = vals [ -1 ]

				if len ( vals ) == 2:
					module = '.'.join ( vals [ : -1 ] )
					modbase = vals [ 0 ]
				else:
					modbase = vals [ 0 ]
					module = '.'.join ( vals [ 1 : -1 ] )
			else:
				h.err_code = 1
				h.err_descr = "Module: '%s' not found (command: '%s')" % ( module, command )
				return 

		else:
			h.err_code = 1
			h.err_descr = "Module and command not specified [Module: '%s' - command: '%s']" % ( module, command )

			return


	if not modbase: 
		modbase = module

	try:
		mod = __import__ ( "modules.%s.%s" % ( modbase, module ) )
	except:
		h.err_code = 2
		h.err_descr = "Could not find module: '%s'" % module
		return

	# Risolvo il modulo. E' scritto in questo modo: modules.modbase.nome_file
	# Esempio: "modules.test.test"
	mod = getattr ( mod, "%s" % modbase )
	mod = getattr ( mod, "%s" % module )

	try:
		cmd = getattr ( mod, command )
	except:
		h.err_code = 3
		h.err_descr = "Could not find command: '%s' on module: '%s" % ( command, module )
		return

	try:
		res = cmd ( h, ** dct )
	except:
		h.err_code = 4
		h.err_descr = "Method '%s.%s' failed with an exception." % ( module, command )
		# TODO: finire salvando tutto il traceback dell'eccezione
		raise
		return

	return res
